﻿using MassTransit;
using System;
using System.Threading.Tasks;

namespace LL2025.Libs.Queue
{
    // 消息契约
    public class OrderSubmitted
    {
        public Guid OrderId { get; set; }
        public string CustomerNumber { get; set; }
        public DateTime Timestamp { get; set; }
    }

    // 总线配置类
    public class BusConfig
    {
        public bool NeedRecived { get; set; } = true; // 是否需要接收消息
        public string RabbitMqHost { get; set; } = "rabbitmq://localhost";
        public string VirtualHost { get; set; } = "/";
        public string Username { get; set; } = "guest";
        public string Password { get; set; } = "guest";
        public ushort PrefetchCount { get; set; } = 16;
        public int ConcurrentMessageLimit { get; set; } = Environment.ProcessorCount;
        public int RetryCount { get; set; } = 3;
        public int RetryIntervalSeconds { get; set; } = 5;
        public bool UseDeadLetterQueue { get; set; } = true;
        public string DeadLetterQueueName { get; set; }
        public string QueueName { get; set; } = "order_submitted_queue"; // 队列名称可以通过配置传递
    }

    // 强类型消费者
    public class OrderSubmittedConsumer : IConsumer<OrderSubmitted>
    {
        public event Action<OrderSubmitted> MessageReceived;

        public Task Consume(ConsumeContext<OrderSubmitted> context)
        {
            MessageReceived?.Invoke(context.Message);
            return Task.CompletedTask;
        }
    }

    // 总线管理器
    public class BusManager : IDisposable
    {
        private readonly IBusControl _busControl;
        private bool _isStarted = false;
        private readonly object _lockObject = new object();
        private readonly BusConfig _config;
        private readonly OrderSubmittedConsumer _consumer;

        public BusManager(BusConfig config)
        {
            _config = config ?? throw new ArgumentNullException(nameof(config));
            _consumer = new OrderSubmittedConsumer();

            if (string.IsNullOrEmpty(config.RabbitMqHost))
                throw new ArgumentException("RabbitMqHost不能为空");

            _busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
            {
                cfg.Host(config.RabbitMqHost, config.VirtualHost, h =>
                {
                    h.Username(config.Username);
                    h.Password(config.Password);
                });
                if (config.NeedRecived)
                {
                    // 配置发布-订阅模式
                    cfg.ReceiveEndpoint(config.QueueName, e =>
                    {
                        e.PrefetchCount = config.PrefetchCount;
                        e.ConcurrentMessageLimit = config.ConcurrentMessageLimit;

                        // 配置重试策略
                        e.UseMessageRetry(r => r.Interval(
                            config.RetryCount,
                            TimeSpan.FromSeconds(config.RetryIntervalSeconds)
                        ));
                        // 设置队列为自动删除
                        e.SetQueueArgument("auto-delete", true);
                        // 注册强类型消费者
                        e.Consumer(() => _consumer);
                        e.Bind(config.QueueName);
                    });
                }
            });
        }

        public async Task StartAsync()
        {
            lock (_lockObject)
            {
                if (_isStarted)
                    return;

                _isStarted = true;
            }

            await _busControl.StartAsync();
        }

        public async Task PublishAsync<T>(T message) where T : class
        {
            if (!_isStarted)
                throw new InvalidOperationException("总线尚未启动");

            await _busControl.Publish(message);
        }

        public async Task StopAsync()
        {
            if (!_isStarted)
                return;

            await _busControl.StopAsync();
            _isStarted = false;
        }

        public void Dispose()
        {
            if (_busControl is IDisposable disposableBus)
            {
                disposableBus.Dispose();
            }
        }

        public event Action<OrderSubmitted> MessageReceived
        {
            add { _consumer.MessageReceived += value; }
            remove { _consumer.MessageReceived -= value; }
        }
    }
}